package com.usian.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.usian.common.exception.CatchCustomException;
import com.usian.common.exception.code.UserStatusCode;
import com.usian.model.common.dtos.ResponseResult;
import com.usian.model.common.enums.AppHttpCodeEnum;
import com.usian.model.user.dtos.LoginDto;
import com.usian.model.user.dtos.SecurityCodeDto;
import com.usian.model.user.pojos.ApUser;
import com.usian.user.common.AppJwtUtil;
import com.usian.user.common.BCrypt;
import com.usian.user.mapper.ApUserMapper;
import com.usian.user.service.ApUserLoginService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@SuppressWarnings("ALL")
public class ApUserLoginServiceImpl implements ApUserLoginService {
    @Autowired
    private ApUserMapper apUserMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public ResponseResult login(LoginDto dto) {
//1.校验参数  设备Id 和 用户名 和 密码 都为空 证明非法
        if(dto.getEquipmentId() == null && (StringUtils.isEmpty(dto.getPassword())&&StringUtils.isEmpty(dto.getPassword()))){
            CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"参数非法");
        }
        // 如果都是空 证明没有登录 需要根据设备Id 进行生成token
        if(!StringUtils.isEmpty(dto.getPassword())&&!StringUtils.isEmpty(dto.getPassword())){
            // 正常登录
            ApUser apUser =  apUserMapper.selectOne(Wrappers.<ApUser>lambdaQuery().eq(ApUser::getPhone, dto.getPhone()));
            if(apUser == null){
                CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"该用户不存在");
            }
            if(!BCrypt.checkpw(dto.getPassword(),apUser.getPassword())){
                CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"密码错误");
            }
            //判断验证码是否正确
            if (dto.getTextCode() !=null && dto.getRandNumCode() !=null) {
                String s = redisTemplate.boundValueOps(dto.getTextCode()).get();
                if (!s.equals(dto.getRandNumCode() + "")) {
                    CatchCustomException.catchs(UserStatusCode.PARAM_FAIL, "验证码不正确，请重新输入");
                }
            }
            // 登录成功 签发令牌
            Map<String, Object> map = new HashMap<>();
            apUser.setPassword("");
            map.put("token", AppJwtUtil.getToken(Long.parseLong(apUser.getId()+"")));
            map.put("user", apUser);
            return ResponseResult.okResult(map);
        }else{
            // 根据设备Id 签发token即可
            if(dto.getEquipmentId() == null){
                CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"非法登录");
            }
            Map<String,Object> map = new HashMap<>();
            // 使用0 区分 是正常登录还是 设备Id
            map.put("token",AppJwtUtil.getToken(0l));
            return ResponseResult.okResult(map);
        }
    }
    /**
     * 注册
     * @param dto
     * @return
     */
    @Override
    public ResponseResult register(LoginDto dto) {
        //判断用户输入手机号不能为空
        if (dto.getPhone() == null){
            CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"手机号不能为空");
        }
        //判断密码不能为空
        if (dto.getPassword() == null){
            CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"密码不能为空");
        }
        //判断验证码是否正确
        String s = redisTemplate.boundValueOps(dto.getTextCode()).get();
        if (!s.equals(dto.getRandNumCode() + "")){
            CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"验证码不正确，请重新输入");
        }
        //生成盐
        String salt = BCrypt.gensalt();
        //密码加密
        String password = BCrypt.hashpw(dto.getPassword(), salt);
        //添加到数据库
        ApUser apUser = new ApUser();
        apUser.setPassword(password);
        apUser.setSalt(salt);
        apUser.setPhone(dto.getPhone());
        apUserMapper.insert(apUser);
        //签发token
        Map map=new HashMap();
        apUser.setPassword("");
        map.put("token",AppJwtUtil.getToken(Long.parseLong(apUser.getId()+"")));
        map.put("user",apUser);
        return ResponseResult.okResult(map);
    }

    // 生成验证码
    public void SecurityCode(LoginDto dto){
        // 检验参数
        if (dto.getPhone() == null && dto.getTextCode() == null){
            CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"参数不能为空");
        }
        if (dto.getPhone().length() != 11){
            CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"请输入正确的手机号格式");
        }
        // 判断是否已经生成验证码
        String s = redisTemplate.boundValueOps(dto.getPhone()).get();
        if (s != null){
            CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"一分钟内只能获取一次验证码");
        }
        String textCode = dto.getTextCode();
        // 生成6位随机数验证码
        int randumCode = (int) ((Math.random() * 9 + 1) * Math.pow(10, 5));

        redisTemplate.boundValueOps(textCode).set(String.valueOf(randumCode));
        redisTemplate.boundValueOps(textCode).expire(5, TimeUnit.MINUTES);

        // 设置验证码发送间隔
        redisTemplate.boundValueOps(dto.getPhone()).set(String.valueOf(randumCode));
        redisTemplate.boundValueOps(dto.getPhone()).expire(1, TimeUnit.MINUTES);

        // 发送消息
        SecurityCodeDto securityCodeDto = new SecurityCodeDto();
        securityCodeDto.setPhone(dto.getPhone());
        securityCodeDto.setRandNumCode(randumCode);
        securityCodeDto.setTextCode(textCode);
        rabbitTemplate.convertAndSend("SmsExchange","smslisten", JSON.toJSONString(securityCodeDto));
    }


}
